package cn.assumejson.springframework.beans.factory.annotation;

import cn.assumejson.springframework.beans.PropertyValues;
import cn.assumejson.springframework.beans.factory.BeanFactory;
import cn.assumejson.springframework.beans.factory.BeanFactoryAware;
import cn.assumejson.springframework.beans.factory.BeansException;
import cn.assumejson.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import cn.assumejson.springframework.beans.factory.support.DefaultListableBeanFactory;
import cn.assumejson.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import cn.assumejson.springframework.beans.factory.support.RootBeanDefinition;
import cn.assumejson.springframework.util.ClassUtils;
import cn.assumejson.springframework.util.ResolvableTypeUtil;
import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 解析@Autowire 注解
 *
 * @author Mr. Li
 * @version 1.0
 * @since 1.0 2021/12/3 10:41
 */
@Slf4j
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, BeanFactoryAware {

    /**
     * 依赖注入集合
     */
    private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

    private DefaultListableBeanFactory beanFactory;


    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    Class.forName("javax.inject.Inject"));
            log.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        } catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        log.info("属性合并时进行属性判断....寻找所有的注入点");
//        findAutowiringMetadata(beanName, beanType, null);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    /**
     * 进行Bean的属性依赖注入
     *
     * @param pvs      属性
     * @param pds      属性描述器
     * @param bean     bean
     * @param beanName beanName
     * @return PropertyValues
     * @throws BeansException BeansException
     */
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        try {
            ResolvableTypeUtil.parsingAttributes(bean, beanFactory);
        } catch (Exception ex) {
            throw new BeansException("AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues is fail!");
        }
        return pvs;
    }


}
